/*********************************************************************
* File: Combat.h
*
* \brief Defines the combat API. 
*********************************************************************/
#pragma once

namespace agents{ class Agent; }
#include "../../engine.h"
#include "../../game/globals.h"
using namespace game;
#include "../interfaces/ICombat.h"
using namespace agents::interfaces;

/** 
* \brief The agent's maximum aim rotation speed in degrees per second. 
**/
#define MAXIMUM_AIM_ROTATION_SPEED 180.0

namespace agents{namespace modules{
	/**
	* \brief Implements the combat API.
	* 
	* Defines actuators, sensors and beliefs relevant for agent
	* combat behavior
	*
	* \author Instituto Superior Tecnico de Lisboa, Portugal
	* \author Technical University of Lisbon, Portugal
	* 
	* \author Agentes Autonomos e Sistemas Multiagente
	* \author Autonomous Agents and Multiagent Systems
	* 
	* \version	1.0
	* \date		2006/2007
	**/
	class Combat: public ICombat {
	public:
		Combat(Agent &owner);
		~Combat();

		void newRound();
		void endCycle();

		//Sensors
		bool hasWeapon(char* name);
		bool hasWeapon(WeaponIds::Enumeration id);
		bool hasPrimaryWeapon();
		bool hasSecondaryWeapon();
		bool hasBomb();
		int armour();
		WeaponIds::Enumeration getPrimaryWeaponId();
		WeaponIds::Enumeration getSecondaryWeaponId();
		/** 
		* \brief Gets the current weapon id. 
		*
		* \see agents::interfaces::ICombat::getCurrentWeapon
		**/
		WeaponIds::Enumeration getCurrentWeapon(){ return _currentWeapon; }
		int getAmmo(void);
		int getAmmoInClip(void);

		//Actuators
		void primaryAttack();
		void secondaryAttack();
		void reloadWeapon();
		bool plantBomb();
		void defuseBomb();
		/** 
		* \brief Whether the agent is in a bomb site. 
		*
		* \see agents::interfaces::ICombat::isInBombSite
		**/
		bool isInBombSite(){ return _isInBombSite; }
		void selectWeapon(char* name);
		void selectWeapon(WeaponIds::Enumeration id);
		void selectPrimaryWeapon();
		void selectSecondaryWeapon();
		void drop();

		Vector getGunPosition();
		Vector getAngles();
		void setAngles(Vector angles);
		void aimLeft();
		void aimRight();
		void aimUp();
		void aimDown();
		void aim(Vector deviation);
		void aimAt(Vector vecPos);
		void aimAtInstantaneously(Vector vecPos);
		bool isAimingAt(Vector target);

		WeaponInfo* getWeaponInfo(WeaponIds::Enumeration id);

		//Auxiliary
		void setIsInBombSite(bool value){ _isInBombSite = value; }
		WeaponIds::Enumeration weaponNameToId(char* name);
		WeaponIds::Enumeration weaponModelNameToId(const char* name);
		int weaponIdToIndex(WeaponIds::Enumeration id);
		int weaponNameToIndex(char* name);
		/** 
		* \brief Sets the current weapon id. 
		**/
		void setCurrentWeapon(WeaponIds::Enumeration weaponId){ _currentWeapon = weaponId; }

		/** 
		* \brief Ammo in clip for each weapons.
		**/
		int ammoInClip[MAX_WEAPONS];
		/** 
		* \brief Total ammo amounts.
		**/
		int ammo[MAX_AMMO_SLOTS];
		/** 
		* \brief Whether the agent has the bomb defuse kit.
		**/
		bool hasDefuser;

	protected:
		float aimIncrement();

		/**
		* \brief  The current weapon. 
		**/
		WeaponIds::Enumeration _currentWeapon;
		/** 
		* \brief The agent. 
		**/
		Agent &_owner;

	private:
		/** 
		* \brief Whether the agent is in a bomb site. 
		**/
		bool _isInBombSite;
	};
}}